﻿using FeedbackHelperLib.Resources;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Info;
using Microsoft.Phone.Marketplace;
using Microsoft.Phone.Tasks;
#if(XNA)
using Microsoft.Xna.Framework.GamerServices;
#endif
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;

namespace FeedbackHelperLib
{
    public enum FeedbackState
    {
        Inactive,
        FirstReview,
        SecondReview,
        Feedback
    }

    /// <summary>
    /// This helper class controls the behaviour of the FeedbackOverlay control
    /// When the app has been launched 5 times the initial prompt is shown
    /// If the user reviews no more prompts are shown
    /// When the app has bee launched 10 times and not been reviewed, the prompt is shown
    /// </summary>
    public class FeedbackHelper
    {
        private const string LAUNCH_COUNT = "LAUNCH_COUNT";
        private const string REVIEWED = "REVIEWED";
        private const int FIRST_COUNT = 4;
        private const int SECOND_COUNT = 10;
        private static string FEEDBACK_ADDRESS = string.Empty;

        private int _launchCount = 0;
        private bool _reviewed = false;

        public static readonly FeedbackHelper Default = new FeedbackHelper();

        private FeedbackState _state = FeedbackState.Inactive;

        private LicenseInformation _licenseInfo = new LicenseInformation();

        public FeedbackState State
        {
            get { return this._state; }
            set { this._state = value; }
        }

        private bool _isTrial = true;
        public bool IsTrial
        {
            get
            {
                return _isTrial;
            }
        }

        private string _appName;

        public string AppName
        {
            get 
            {
                if (string.IsNullOrEmpty(_appName))
                {
                    _appName = GetAppName();
                }
                return _appName;
            }
        }
        

        private string Message { get; set; }
        private string Title { get; set; }
        private string YesText { get; set; }
        private string NoText { get; set; }

        private FeedbackHelper()
        {
            CheckLicense();
        }

        /// <summary>
        /// Loads last state from storage and works out the new state
        /// </summary>
        private void LoadState()
        {
            try
            {
                this._launchCount = StorageHelper.GetSetting<int>(LAUNCH_COUNT);
                this._reviewed = StorageHelper.GetSetting<bool>(REVIEWED);

                if (!this._reviewed)
                {
                    this._launchCount++;

                    if (this._launchCount == FIRST_COUNT)
                        this._state = FeedbackState.FirstReview;
                    else if (this._launchCount == SECOND_COUNT)
                        this._state = FeedbackState.SecondReview;

                    this.StoreState();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("FeedbackHelper.LoadState - Failed to load state, Exception: {0}", ex.ToString()));
            }
        }

        /// <summary>
        /// Stores current state
        /// </summary>
        private void StoreState()
        {
            try
            {
                StorageHelper.StoreSetting(LAUNCH_COUNT, this._launchCount, true);
                StorageHelper.StoreSetting(REVIEWED, this._reviewed, true);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("FeedbackHelper.StoreState - Failed to store state, Exception: {0}", ex.ToString()));
            }
        }

        /// <summary>
        /// Call when user has reviewed
        /// </summary>
        public void Reviewed()
        {
            this._reviewed = true;

            this.StoreState();
        }

        public void Initialise(string feedbackAddress)
        {
            FEEDBACK_ADDRESS = feedbackAddress;
            // Only load state if not trial
            if (!IsTrial)
            {
                this.LoadState();

                // Uncomment for testing
                // this._state = FeedbackState.FirstReview;
                // this._state = FeedbackState.SecondReview;

                if (this.State == FeedbackState.FirstReview)
                {
                    this.Title = string.Format(FeedbackResources.RatingTitle, AppName) ;
                    this.Message = FeedbackResources.RatingMessage1;
                    this.YesText = FeedbackResources.RatingYes;
                    this.NoText = FeedbackResources.RatingNo;

                    this.ShowMessage();
                }
                else if (this.State == FeedbackState.SecondReview)
                {
                    this.Title = string.Format(FeedbackResources.RatingTitle, AppName);
                    this.Message = FeedbackResources.RatingMessage2;
                    this.YesText = FeedbackResources.RatingYes;
                    this.NoText = FeedbackResources.RatingNo;

                    this.ShowMessage();
                }
            }
        }

        private void ShowMessage()
        {
#if(XNA)
            int loop = 0;

            // Check guide is not open
            while (Guide.IsVisible)
            {
                if (loop > 20) // Max 2s
                    return;
                loop++;

                System.Threading.Thread.Sleep(100);
            }

            Guide.BeginShowMessageBox(this.Title, this.Message,
                new List<string>() { this.YesText, this.NoText },
                0, MessageBoxIcon.None, (r) =>
                {
                    var result = Guide.EndShowMessageBox(r);
                    if (result.HasValue && result.Value == 0)
                        OnYesClick();
                    else
                        OnNoClick();

                }, null);
#else
            CustomMessageBox messageBox = new CustomMessageBox()
            {
                Caption = this.Title,
                Message = this.Message,
                LeftButtonContent = this.YesText,
                RightButtonContent = this.NoText
            };

            messageBox.Dismissed += (s1, e1) =>
            {
                switch (e1.Result)
                {
                    case CustomMessageBoxResult.LeftButton:
                        OnYesClick();
                        break;
                    default:
                        OnNoClick();
                        break;
                }
            };

            messageBox.Show();
#endif


        }

        private void OnNoClick()
        {
            if (FeedbackHelper.Default.State == FeedbackState.FirstReview)
            {
                this.Title = string.Format(FeedbackResources.FeedbackTitle,AppName);
                this.Message = string.Format(FeedbackResources.FeedbackMessage1, AppName);
                this.YesText = FeedbackResources.FeedbackYes;
                this.NoText = FeedbackResources.FeedbackNo;

                FeedbackHelper.Default.State = FeedbackState.Feedback;
                ShowMessage();
            }
        }

        private void OnYesClick()
        {
            if (FeedbackHelper.Default.State == FeedbackState.FirstReview)
            {
                this.Review();
            }
            else if (FeedbackHelper.Default.State == FeedbackState.SecondReview)
            {
                this.Review();
            }
            else if (FeedbackHelper.Default.State == FeedbackState.Feedback)
            {
                this.Feedback();
            }
        }

        private void Review()
        {
            this.Reviewed();
            try
            {
                var marketplace = new MarketplaceReviewTask();
                marketplace.Show();
            }
            catch { }
        }

        private void Feedback()
        {
            // Application version
            var asm = System.Reflection.Assembly.GetExecutingAssembly();
            var parts = asm.FullName.Split(',');
            var version = parts[1].Split('=')[1];

            // Body text including hardware, firmware and software info
            string body = string.Format(FeedbackResources.FeedbackBody,
                DeviceStatus.DeviceName,
                DeviceStatus.DeviceManufacturer,
                DeviceStatus.DeviceFirmwareVersion,
                DeviceStatus.DeviceHardwareVersion,
                version);

            // Email task
            try
            {
                var email = new EmailComposeTask();
                email.To = FEEDBACK_ADDRESS;
                email.Subject = string.Format(FeedbackResources.FeedbackSubject, AppName);
                email.Body = body;

                email.Show();
            }
            catch { }
        }

        /// <summary>
        /// Check the current license information for this application
        /// </summary>
        private void CheckLicense()
        {
            // When debugging, we want to simulate a trial mode experience. The following conditional allows us to set the _isTrial 
            // property to simulate trial mode being on or off. 
#if DEBUG
#if XNA
            _isTrial = false;
#else
            string message = "This sample demonstrates the implementation of a trial mode in an application." +
                               "Press 'OK' to simulate trial mode. Press 'Cancel' to run the application in normal mode.";
            if (MessageBox.Show(message, "Debug Trial",
                 MessageBoxButton.OKCancel) == MessageBoxResult.OK)
            {
                _isTrial = true;
            }
            else
            {
                _isTrial = false;
            }
#endif
#else
#if XNA
            _isTrial = Microsoft.Xna.Framework.GamerServices.Guide.IsTrialMode;
#else
            _isTrial = _licenseInfo.IsTrial();
#endif
#endif
        }

        public string GetAppName()
        {
            string name = "";
            var executingAssembly = System.Reflection.Assembly.GetExecutingAssembly();
            var customAttributes = executingAssembly.GetCustomAttributes(typeof(System.Reflection.AssemblyTitleAttribute), false);
            if (customAttributes != null)
            {
                var assemblyName = customAttributes[0] as System.Reflection.AssemblyTitleAttribute;
                name = assemblyName.Title;
            }

            return name;
        }
    }
}
